require "import"
import "android.app.*"
import "android.content.*"
import "android.content.pm.*"
import "android.net.Uri"
import "android.widget.*"
import "android.view.*"
import "android.widget.Toast"
import "java.io.File"
import "android.os.Environment"
import "com.androlua.LuaDialog"
import "com.androlua.LuaUtil"
import "android.media.MediaPlayer"
import "java.io.FileOutputStream"
import "java.io.InputStream"
import "java.util.zip.ZipFile"
import "android.util.Log"
import "java.util.concurrent.ConcurrentHashMap"
import "luajava"
import "java.text.SimpleDateFormat"
import "java.util.Date"

local layout=LinearLayout(service)
layout.setOrientation(LinearLayout.VERTICAL)

local topBar=LinearLayout(service)
topBar.setOrientation(LinearLayout.HORIZONTAL)
topBar.setGravity(Gravity.CENTER_VERTICAL)
topBar.setPadding(15,15,15,15)
topBar.setBackgroundColor(0xFFF5F5F5)

local titleLayout=LinearLayout(service)
titleLayout.setOrientation(LinearLayout.VERTICAL)
titleLayout.setGravity(Gravity.CENTER)

local titleText=TextView(service)
titleText.setText(" SAYAHFETHI تطبيقات أندرويد")
titleText.setTextSize(18)
titleText.setTextColor(0xFF000000)
titleLayout.addView(titleText)

local devText=TextView(service)
devText.setText("تم تطويره بواسطة سايح فتحي")
devText.setTextSize(12)
devText.setTextColor(0xFF808080)
titleLayout.addView(devText)

local counterLayout=LinearLayout(service)
counterLayout.setOrientation(LinearLayout.HORIZONTAL)
counterLayout.setGravity(Gravity.CENTER)

local counterText=TextView(service)
counterText.setText("0 تطبيق")
counterText.setTextSize(14)
counterText.setTextColor(0xFF808080)
counterLayout.addView(counterText)

local componentCounterText=TextView(service)
componentCounterText.setText(" (0 مكوّن)")
componentCounterText.setTextSize(14)
componentCounterText.setTextColor(0xFF808080)
componentCounterText.setVisibility(View.GONE)
counterLayout.addView(componentCounterText)

titleLayout.addView(counterLayout)

local titleParams=LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT)
titleParams.gravity=Gravity.CENTER
topBar.addView(titleLayout,titleParams)

layout.addView(topBar)

local headerLayout=LinearLayout(service)
headerLayout.setOrientation(LinearLayout.HORIZONTAL)
headerLayout.setGravity(Gravity.CENTER_VERTICAL)
headerLayout.setPadding(20,10,20,10)

local appTypeSpinner=Spinner(service)
local types={"جميع التطبيقات","التطبيقات المثبتة","تطبيقات النظام","المفضلة"}
local adapterSpinner=ArrayAdapter(service,android.R.layout.simple_spinner_item,types)
adapterSpinner.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
appTypeSpinner.setAdapter(adapterSpinner)

local spinnerParams=LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT)
headerLayout.addView(appTypeSpinner,spinnerParams)

layout.addView(headerLayout)

local searchEditText=EditText(service)
searchEditText.setHint("البحث عن تطبيق")
layout.addView(searchEditText)

local listView=ListView(service)
local listParams=LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,0)
listParams.weight=1
listView.setLayoutParams(listParams)
layout.addView(listView)

local exitButton=Button(service)
exitButton.setText("خروج")
exitButton.setTextColor(0xFFFFFFFF)
exitButton.setBackgroundColor(0xFFE53935)
local exitParams=LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT)
exitParams.setMargins(15,15,15,15)
exitButton.setLayoutParams(exitParams)
layout.addView(exitButton)

local packageManager=service.getPackageManager()
local appData=luajava.newInstance("java.util.concurrent.ConcurrentHashMap")
local allAppNames={}
local isFavoritesMode=false
local currentAudioPlayer=nil

local function saveFavorites(favorites,prefsName)
 local prefs=service.getSharedPreferences(prefsName,Context.MODE_PRIVATE)
 local editor=prefs.edit()
 local favoritesString=table.concat(favorites,",")
 editor.putString("favoriteItems",favoritesString)
 editor.commit()
end

local function loadFavorites(prefsName)
 local prefs=service.getSharedPreferences(prefsName,Context.MODE_PRIVATE)
 local favoritesString=prefs.getString("favoriteItems","")
 local favorites={}
 if favoritesString~="" then
  for pkg in string.gmatch(favoritesString,"([^,]+)") do
   table.insert(favorites,pkg)
  end
 end
 return favorites
end

local function saveFavoriteComponents(favs)
 local prefs=service.getSharedPreferences("ComponentFavorites",Context.MODE_PRIVATE)
 editor=prefs.edit()
 local favString=table.concat(favs,";")
 editor.putString("favoriteComponents",favString)
 editor.commit()
end

local function loadFavoriteComponents()
 local prefs=service.getSharedPreferences("ComponentFavorites",Context.MODE_PRIVATE)
 local favString=prefs.getString("favoriteComponents","")
 local favs={}
 if favString~="" then
  for pkgAndComp in string.gmatch(favString,"([^;]+)") do
   table.insert(favs,pkgAndComp)
  end
 end
 return favs
end

local favoritePackages=loadFavorites("AppFavorites")
local favoriteComponents=loadFavoriteComponents()

local function updateCounters(appCount,componentCount)
 if isFavoritesMode then
  counterText.setText(string.format("%d تطبيق",appCount))
  componentCounterText.setText(string.format(" (%d مكوّن)",componentCount))
  componentCounterText.setVisibility(View.VISIBLE)
 else
  counterText.setText(string.format("%d تطبيق",appCount))
  componentCounterText.setVisibility(View.GONE)
 end
end

local function loadFavoritesData(searchQuery)
 appData.clear()
 allAppNames={}
 local appCount=0
 local componentCount=0
 for _,pkg in ipairs(favoritePackages) do
  local packageInfo=packageManager.getPackageInfo(pkg,0)
  if packageInfo then
   local appLabel=tostring(packageManager.getApplicationLabel(packageInfo.applicationInfo))
   local versionName=tostring(packageInfo.versionName or "1.0")
   local displayName=string.format("%s_v%s",appLabel,versionName)
   appData.put(displayName,{packageName=pkg,isComponent=false})
   table.insert(allAppNames,displayName)
   appCount=appCount+1
  end
 end
 for _,entry in ipairs(favoriteComponents) do
  local packageName,componentName=entry:match("(.+)|(.+)")
  if packageName and componentName then
   local packageInfo=packageManager.getPackageInfo(packageName,0)
   if packageInfo then
    local appLabel=tostring(packageManager.getApplicationLabel(packageInfo.applicationInfo))
    local displayName=string.format("%s (%s) [Star]",componentName,appLabel)
    appData.put(displayName,{packageName=packageName,componentName=componentName,isComponent=true})
    table.insert(allAppNames,displayName)
    componentCount=componentCount+1
   end
  end
 end
 table.sort(allAppNames,function(a,b) return string.lower(a)<string.lower(b) end)
 local filtered={}
 local filteredComponentCount=0
 local filteredAppCount=0
 for _,itemName in ipairs(allAppNames) do
  if string.lower(itemName):find(string.lower(searchQuery)) then
   table.insert(filtered,itemName)
   local data=appData.get(itemName)
   if data and data.isComponent then filteredComponentCount=filteredComponentCount+1 else filteredAppCount=filteredAppCount+1 end
  end
 end
 listView.setAdapter(ArrayAdapter(service,android.R.layout.simple_list_item_1,filtered))
 updateCounters(filteredAppCount,filteredComponentCount)
end

local function loadApplications(appType,searchQuery)
 appData.clear()
 allAppNames={}
 isFavoritesMode=(appType=="المفضلة")
 searchEditText.setHint(isFavoritesMode and "البحث عن مكوّن أو تطبيق" or "البحث عن تطبيق")
 if isFavoritesMode then loadFavoritesData(searchQuery) return end
 local flags=PackageManager.GET_META_DATA
 local applications=packageManager.getInstalledApplications(flags)
 for i=0,applications.size()-1 do
  local appInfo=applications.get(i)
  local appFlags=appInfo.flags
  local isSystemApp=(appFlags & ApplicationInfo.FLAG_SYSTEM)~=0
  local isUpdatedSystemApp=(appFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)~=0
  local appPackage=appInfo.packageName
  local includeApp=false
  if appType=="جميع التطبيقات" then includeApp=true
  elseif appType=="تطبيقات النظام" then if isSystemApp then includeApp=true end
  else if not isSystemApp or isUpdatedSystemApp then includeApp=true end end
  local isFav=false
  for _,favPkg in ipairs(favoritePackages) do if favPkg==appPackage then isFav=true break end end
  if includeApp and not isFav then
   local appLabel=tostring(appInfo.loadLabel(packageManager))
   local packageInfo=packageManager.getPackageInfo(appPackage,0)
   local versionName=tostring(packageInfo.versionName or "1.0")
   local displayName=string.format("%s_v%s",appLabel,versionName)
   appData.put(displayName,{packageName=appPackage,isComponent=false})
   table.insert(allAppNames,displayName)
  end
 end
 table.sort(allAppNames,function(a,b) return string.lower(a)<string.lower(b) end)
 local filtered={}
 for _,itemName in ipairs(allAppNames) do
  if string.lower(itemName):find(string.lower(searchQuery)) then table.insert(filtered,itemName) end
 end
 listView.setAdapter(ArrayAdapter(service,android.R.layout.simple_list_item_1,filtered))
 updateCounters(#filtered,0)
end

local function saveSelection(index)
 local prefs=service.getSharedPreferences("AppTypeSelection",Context.MODE_PRIVATE)
 local editor=prefs.edit()
 editor.putInt("selectedType",index)
 editor.commit()
end

local function loadSelection()
 local prefs=service.getSharedPreferences("AppTypeSelection",Context.MODE_PRIVATE)
 return prefs.getInt("selectedType",0)
end

appTypeSpinner.onItemSelected=function(parent,view,position,id)
 saveSelection(position)
 local currentQuery=tostring(searchEditText.getText())
 loadApplications(types[position+1],currentQuery)
end

local lastSelection=loadSelection()
appTypeSpinner.setSelection(lastSelection)
loadApplications(types[lastSelection+1],"")

searchEditText.addTextChangedListener{onTextChanged=function(s)
 local query=tostring(s)
 local currentType=types[appTypeSpinner.getSelectedItemPosition()+1]
 loadApplications(currentType,query)
end}

local dlg=LuaDialog(service)
dlg.setView(layout)
dlg.setCancelable(true)

exitButton.setOnClickListener(function()
 dlg.dismiss()
end)

dlg.show()
dlg.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)

listView.onItemClick=function(parent,view,position,id)
 local selectedName=parent.getAdapter().getItem(position)
 local data=appData.get(selectedName)
 if data and data.isComponent then
  local intent=Intent()
  intent.setClassName(data.packageName,data.componentName)
  service.startActivity(intent)
  dlg.dismiss()
 elseif data and not data.isComponent then
  local launchIntent=packageManager.getLaunchIntentForPackage(data.packageName)
  if launchIntent then
   service.startActivity(launchIntent)
   dlg.dismiss()
  else
   Toast.makeText(service,"تعذر فتح "..selectedName,Toast.LENGTH_SHORT).show()
  end
 end
end

local function displayComponents(packageName)
 local packageInfo=packageManager.getPackageInfo(packageName,PackageManager.GET_ACTIVITIES)
 local allComponentNames={}
 local function isFavoriteComponent(compName)
  local favEntry=packageName.."|"..compName
  for _,fav in ipairs(favoriteComponents) do if fav==favEntry then return true end end
  return false
 end
 if packageInfo.activities then
  local activities=luajava.astable(packageInfo.activities)
  for i,activityInfo in ipairs(activities) do
   local name=activityInfo.name
   if not isFavoriteComponent(name) then table.insert(allComponentNames,name) end
  end
 end
 if #allComponentNames>0 then
  local actDialog=LuaDialog(service)
  local dialogLayout=LinearLayout(service)
  dialogLayout.setOrientation(LinearLayout.VERTICAL)
  local componentHeader=LinearLayout(service)
  componentHeader.setOrientation(LinearLayout.HORIZONTAL)
  componentHeader.setGravity(Gravity.CENTER_VERTICAL)
  componentHeader.setPadding(20,10,20,10)
  local componentTitle=TextView(service)
  componentTitle.setText("الأنشطة")
  componentTitle.setTextSize(18)
  componentHeader.addView(componentTitle)
  local componentCounter=TextView(service)
  componentCounter.setText(string.format(" (%d)",#allComponentNames))
  componentCounter.setTextSize(14)
  componentCounter.setTextColor(0xFF808080)
  componentHeader.addView(componentCounter)
  local componentSearch=EditText(service)
  componentSearch.setHint("البحث عن نشاط...")
  local searchParams=LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.WRAP_CONTENT)
  searchParams.weight=1
  searchParams.leftMargin=10
  componentSearch.setLayoutParams(searchParams)
  componentHeader.addView(componentSearch)
  dialogLayout.addView(componentHeader)
  local componentList=ListView(service)
  dialogLayout.addView(componentList)
  local filteredComponents=allComponentNames
  local adapter=ArrayAdapter(service,android.R.layout.simple_list_item_1,filteredComponents)
  componentList.setAdapter(adapter)
  actDialog.setView(dialogLayout)
  actDialog.setNegativeButton("عودة",nil)
  actDialog.show()
  componentSearch.addTextChangedListener{onTextChanged=function(s)
   local query=tostring(s)
   filteredComponents={}
   for _,componentName in ipairs(allComponentNames) do
    if string.lower(componentName):find(string.lower(query)) then table.insert(filteredComponents,componentName) end
   end
   componentList.setAdapter(ArrayAdapter(service,android.R.layout.simple_list_item_1,filteredComponents))
   componentCounter.setText(string.format(" (%d)",#filteredComponents))
  end}
  componentList.onItemClick=function(parent,view,position,id)
   local selectedComponent=parent.getAdapter().getItem(position)
   local componentName=selectedComponent
   if componentName then
    local intent=Intent()
    intent.setClassName(packageName,componentName)
    service.startActivity(intent)
    actDialog.dismiss()
    dlg.dismiss()
   end
  end
  componentList.onItemLongClick=function(parent,view,position,id)
   local selectedComponent=parent.getAdapter().getItem(position)
   local componentName=selectedComponent
   local favEntry=packageName.."|"..componentName
   local isFav=false
   for _,fav in ipairs(favoriteComponents) do if fav==favEntry then isFav=true break end end
   local menu=LuaDialog(service)
   menu.setTitle(componentName)
   local options={isFav and "إزالة من المفضلة" or "إضافة إلى المفضلة","نسخ الكود"}
   menu.setItems(options)
   menu.onItemClick=function(parent,view,pos,id)
    if pos==0 then
     if isFav then
      for i,fav in ipairs(favoriteComponents) do if fav==favEntry then table.remove(favoriteComponents,i) break end end
      Toast.makeText(service,"تمت الإزالة من المفضلة",Toast.LENGTH_SHORT).show()
     else
      table.insert(favoriteComponents,favEntry)
      Toast.makeText(service,"تمت الإضافة إلى المفضلة",Toast.LENGTH_SHORT).show()
     end
     saveFavoriteComponents(favoriteComponents)
     local packageInfo=packageManager.getPackageInfo(packageName,PackageManager.GET_ACTIVITIES)
     local newComponentNames={}
     local function isFavoriteComponent(compName)
      local favEntry=packageName.."|"..compName
      for _,fav in ipairs(favoriteComponents) do if fav==favEntry then return true end end
      return false
     end
     if packageInfo.activities then
      local activities=luajava.astable(packageInfo.activities)
      for i,activityInfo in ipairs(activities) do
       local name=activityInfo.name
       if not isFavoriteComponent(name) then table.insert(newComponentNames,name) end
      end
     end
     local currentQuery=tostring(componentSearch.getText())
     local reFilteredList={}
     for _,compName in ipairs(newComponentNames) do
      if string.lower(compName):find(string.lower(currentQuery)) then table.insert(reFilteredList,compName) end
     end
     componentList.setAdapter(ArrayAdapter(service,android.R.layout.simple_list_item_1,reFilteredList))
     componentCounter.setText(string.format(" (%d)",#reFilteredList))
     allComponentNames=newComponentNames
    elseif pos==1 then
     local code='i=luajava.bindClass("android.content.Intent")()\ni.setClassName("'..packageName..'", "'..componentName..'")\nservice.startActivity(i)'
     service.copy(code)
     Toast.makeText(service,"تم نسخ الكود إلى الحافظة!",Toast.LENGTH_SHORT).show()
    end
    menu.dismiss()
   end
   menu.setNegativeButton("عودة",nil)
   menu.show()
   return true
  end
 else
  Toast.makeText(service,"لم يتم العثور على أنشطة لهذا التطبيق.",Toast.LENGTH_SHORT).show()
 end
end

local function playAudio(apkPath,entryName)
 if currentAudioPlayer then
  if currentAudioPlayer.isPlaying() then currentAudioPlayer.stop() end
  currentAudioPlayer.release()
  currentAudioPlayer=nil
 end
 local success,err=pcall(function()
  local zipFile=ZipFile(apkPath)
  local inputStream=zipFile.getInputStream(zipFile.getEntry(entryName))
  local tempDir=service.getCacheDir()
  local tempFile=File(tempDir,entryName:match("([^/]+)$"))
  local outputStream=FileOutputStream(tempFile)
  LuaUtil.copyFile(inputStream,outputStream)
  inputStream.close()
  outputStream.close()
  zipFile.close()
  local player=MediaPlayer()
  player.setDataSource(tempFile.getAbsolutePath())
  player.prepare()
  player.start()
  currentAudioPlayer=player
  Toast.makeText(service,"جاري التشغيل: "..tempFile.getName(),Toast.LENGTH_SHORT).show()
 end)
 if not success then Toast.makeText(service,"خطأ في تشغيل الصوت: "..tostring(err),Toast.LENGTH_SHORT).show() end
end

local function downloadAudio(apkPath,entryName,fileName)
 local success,err=pcall(function()
  local downloadsDir=File(File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),"مدير تطبيقات أندرويد SAYAHFETHI"),"الصوت المستخرج")
  downloadsDir.mkdirs()
  local zipFile=ZipFile(apkPath)
  local inputStream=zipFile.getInputStream(zipFile.getEntry(entryName))
  local outputFile=File(downloadsDir,fileName)
  local outputStream=FileOutputStream(outputFile)
  LuaUtil.copyFile(inputStream,outputStream)
  inputStream.close()
  outputStream.close()
  zipFile.close()
  Toast.makeText(service,"تم حفظ الصوت في "..outputFile.getAbsolutePath(),Toast.LENGTH_LONG).show()
 end)
 if not success then Toast.makeText(service,"خطأ في حفظ الصوت: "..tostring(err),Toast.LENGTH_SHORT).show() end
end

local function extractAllAudio(apkPath,audioMap)
 local downloadsDir=File(File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),"مدير تطبيقات أندرويد SAYAHFETHI"),"الصوت المستخرج")
 downloadsDir.mkdirs()
 local totalDownloads=0
 local successfulDownloads=0
 local failedDownloads=0
 local zipFile=ZipFile(apkPath)
 for fileName,entryName in pairs(audioMap) do
  totalDownloads=totalDownloads+1
  local success,err=pcall(function()
   local inputStream=zipFile.getInputStream(zipFile.getEntry(entryName))
   local outputFile=File(downloadsDir,fileName)
   local outputStream=FileOutputStream(outputFile)
   LuaUtil.copyFile(inputStream,outputStream)
   inputStream.close()
   outputStream.close()
  end)
  if success then successfulDownloads=successfulDownloads+1 else failedDownloads=failedDownloads+1 end
 end
 zipFile.close()
 local downloadsMessage=successfulDownloads>0 and string.format("تم استخراج %d ملف بنجاح إلى '%s'.",successfulDownloads,downloadsDir.getAbsolutePath()) or "لم يتم استخراج أي ملفات."
 Toast.makeText(service,downloadsMessage,Toast.LENGTH_LONG).show()
end

local function extractAudioFiles(packageName)
 local packageInfo=packageManager.getPackageInfo(packageName,0)
 local apkPath=packageInfo.applicationInfo.sourceDir
 local audioFiles={}
 local audioMap={}
 local function getAudioResources(zipFile)
  local entries=zipFile.entries()
  while entries.hasMoreElements() do
   local entry=entries.nextElement()
   local name=entry.getName()
   if not entry.isDirectory() and (name:lower():find(".mp3$") or name:lower():find(".ogg$") or name:lower():find(".wav$")) then
    local filename=name:match("([^/]+)$")
    table.insert(audioFiles,filename)
    audioMap[filename]=name
   end
  end
 end
 pcall(function()
  local zipFile=ZipFile(apkPath)
  getAudioResources(zipFile)
  zipFile.close()
 end)
 if #audioFiles>0 then
  local audioDialog=LuaDialog(service)
  local dialogLayout=LinearLayout(service)
  dialogLayout.setOrientation(LinearLayout.VERTICAL)
  local headerLayout=LinearLayout(service)
  headerLayout.setOrientation(LinearLayout.HORIZONTAL)
  headerLayout.setGravity(Gravity.CENTER_VERTICAL)
  local titleAndCounterLayout=LinearLayout(service)
  titleAndCounterLayout.setOrientation(LinearLayout.VERTICAL)
  local title=TextView(service)
  title.setText("الصوت المستخرج")
  title.setTextSize(18)
  titleAndCounterLayout.addView(title)
  local counter=TextView(service)
  counter.setText(string.format("%d ملف تم العثور عليه",#audioFiles))
  counter.setTextSize(14)
  counter.setTextColor(0xFF808080)
  titleAndCounterLayout.addView(counter)
  local titleParams=LinearLayout.LayoutParams(0,-2,1)
  headerLayout.addView(titleAndCounterLayout,titleParams)
  local downloadAllButton=Button(service)
  downloadAllButton.setText("استخراج الكل")
  downloadAllButton.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT))
  headerLayout.addView(downloadAllButton)
  local searchEditText=EditText(service)
  searchEditText.setHint("البحث عن صوت...")
  local searchParams=LinearLayout.LayoutParams(0,-2,1)
  searchEditText.setLayoutParams(searchParams)
  searchEditText.setPadding(10,0,10,0)
  headerLayout.addView(searchEditText)
  dialogLayout.addView(headerLayout)
  local audioList=ListView(service)
  local adapter=ArrayAdapter(service,android.R.layout.simple_list_item_1,audioFiles)
  audioList.setAdapter(adapter)
  dialogLayout.addView(audioList)
  audioDialog.setView(dialogLayout)
  audioDialog.setNegativeButton("إغلاق",nil)
  audioDialog.show()
  downloadAllButton.onClick=function()
   local confirmDialog=LuaDialog(service)
   confirmDialog.setTitle("هل تريد استخراج جميع ملفات الصوت من هذا التطبيق؟")
   confirmDialog.setPositiveButton("نعم",function() extractAllAudio(apkPath,audioMap) confirmDialog.dismiss() end)
   confirmDialog.setNegativeButton("لا",function() confirmDialog.dismiss() end)
   confirmDialog.show()
  end
  searchEditText.addTextChangedListener{onTextChanged=function(s)
   local query=tostring(s)
   local filtered={}
   for _,audioName in ipairs(audioFiles) do
    if string.lower(audioName):find(string.lower(query)) then table.insert(filtered,audioName) end
   end
   audioList.setAdapter(ArrayAdapter(service,android.R.layout.simple_list_item_1,filtered))
   counter.setText(string.format("%d ملف تم العثور عليه",#filtered))
  end}
  audioList.onItemClick=function(parent,view,position,id)
   local selectedAudio=parent.getAdapter().getItem(position)
   local fullPath=audioMap[selectedAudio]
   playAudio(apkPath,fullPath)
  end
  audioList.onItemLongClick=function(parent,view,position,id)
   local selectedAudio=parent.getAdapter().getItem(position)
   local fullPath=audioMap[selectedAudio]
   downloadAudio(apkPath,fullPath,selectedAudio)
   return true
  end
 else
  Toast.makeText(service,"لم يتم العثور على ملفات صوت في هذا التطبيق.",Toast.LENGTH_SHORT).show()
 end
end

local function extractAllImages(apkPath,imageMap)
 local imagesDir=File(File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),"مدير تطبيقات أندرويد SAYAHFETHI"),"الصور المستخرجة")
 imagesDir.mkdirs()
 local total=0
 local success=0
 local failed=0
 local zipFile=ZipFile(apkPath)
 for fileName,entryName in pairs(imageMap) do
  total=total+1
  local ok,err=pcall(function()
   local input=zipFile.getInputStream(zipFile.getEntry(entryName))
   local output=FileOutputStream(File(imagesDir,fileName))
   LuaUtil.copyFile(input,output)
   input.close()
   output.close()
  end)
  if ok then success=success+1 else failed=failed+1 end
 end
 zipFile.close()
 local msg=success>0 and string.format("تم استخراج %d صورة بنجاح إلى:\n%s",success,imagesDir.getAbsolutePath()) or "فشل استخراج الصور."
 Toast.makeText(service,msg,Toast.LENGTH_LONG).show()
end

local function extractImageFiles(packageName)
 local packageInfo=packageManager.getPackageInfo(packageName,0)
 local apkPath=packageInfo.applicationInfo.sourceDir
 local imageFiles={}
 local imageMap={}
 local function scanImages(zipFile)
  local entries=zipFile.entries()
  while entries.hasMoreElements() do
   local entry=entries.nextElement()
   local name=entry.getName()
   if not entry.isDirectory() then
    local lower=name:lower()
    if lower:find("%.png$") or lower:find("%.jpg$") or lower:find("%.jpeg$") or lower:find("%.webp$") or lower:find("%.gif$") then
     local filename=name:match("([^/]+)$")
     table.insert(imageFiles,filename.." ← "..name)
     imageMap[filename]=name
    end
   end
  end
 end
 local ok=pcall(function()
  local zip=ZipFile(apkPath)
  scanImages(zip)
  zip.close()
 end)
 if not ok or #imageFiles==0 then
  Toast.makeText(service,"لم يتم العثور على صور في هذا التطبيق.",Toast.LENGTH_SHORT).show()
  return
 end
 table.sort(imageFiles)
 local imgDialog=LuaDialog(service)
 local layout=LinearLayout(service)
 layout.setOrientation(LinearLayout.VERTICAL)
 local header=LinearLayout(service)
 header.setOrientation(LinearLayout.HORIZONTAL)
 header.setGravity(Gravity.CENTER_VERTICAL)
 header.setPadding(20,10,20,10)
 local titleLayout=LinearLayout(service)
 titleLayout.setOrientation(LinearLayout.VERTICAL)
 local title=TextView(service)
 title.setText("الصور المستخرجة")
 title.setTextSize(18)
 titleLayout.addView(title)
 local count=TextView(service)
 count.setText(string.format("%d صورة",#imageFiles))
 count.setTextSize(14)
 count.setTextColor(0xFF808080)
 titleLayout.addView(count)
 header.addView(titleLayout,LinearLayout.LayoutParams(0,-2,1))
 local extractAllBtn=Button(service)
 extractAllBtn.setText("استخراج الكل")
 header.addView(extractAllBtn)
 local search=EditText(service)
 search.setHint("البحث في الصور...")
 search.setLayoutParams(LinearLayout.LayoutParams(0,-2,1))
 search.setPadding(10,0,10,0)
 header.addView(search)
 layout.addView(header)
 local imgList=ListView(service)
 local adapter=ArrayAdapter(service,android.R.layout.simple_list_item_1,imageFiles)
 imgList.setAdapter(adapter)
 layout.addView(imgList)
 imgDialog.setView(layout)
 imgDialog.setNegativeButton("إغلاق",nil)
 imgDialog.show()
 extractAllBtn.onClick=function()
  local confirm=LuaDialog(service)
  confirm.setTitle("استخراج جميع الصور؟")
  confirm.setMessage(string.format("سيتم استخراج %d صورة إلى مجلد Downloads/مدير تطبيقات أندرويد SAYAHFETHI/الصور المستخرجة",#imageFiles))
  confirm.setPositiveButton("نعم",function()
   extractAllImages(apkPath,imageMap)
   confirm.dismiss()
  end)
  confirm.setNegativeButton("لا",function() confirm.dismiss() end)
  confirm.show()
 end
 search.addTextChangedListener{onTextChanged=function(s)
  local q=string.lower(tostring(s))
  local filtered={}
  for _,v in ipairs(imageFiles) do
   if string.lower(v):find(q) then table.insert(filtered,v) end
  end
  imgList.setAdapter(ArrayAdapter(service,android.R.layout.simple_list_item_1,filtered))
  count.setText(string.format("%d صورة",#filtered))
 end}
 imgList.onItemLongClick=function(parent,view,pos,id)
  local item=parent.getAdapter().getItem(pos)
  local filename=item:match("^([^ ]+)")
  local entry=imageMap[filename]
  local imagesDir=File(File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),"مدير تطبيقات أندرويد SAYAHFETHI"),"الصور المستخرجة")
  imagesDir.mkdirs()
  local ok=pcall(function()
   local zip=ZipFile(apkPath)
   local input=zip.getInputStream(zip.getEntry(entry))
   local output=FileOutputStream(File(imagesDir,filename))
   LuaUtil.copyFile(input,output)
   input.close()
   output.close()
   zip.close()
  end)
  if ok then
   Toast.makeText(service,"تم حفظ الصورة:\n"..File(imagesDir,filename).getAbsolutePath(),Toast.LENGTH_LONG).show()
  else
   Toast.makeText(service,"فشل حفظ الصورة",Toast.LENGTH_SHORT).show()
  end
  return true
 end
end

local function showAppDetails(packageName)
 local packageInfo=packageManager.getPackageInfo(packageName,0)
 local appDetailsDialog=LuaDialog(service)
 local scrollLayout=ScrollView(service)
 local detailsLayout=LinearLayout(service)
 detailsLayout.setOrientation(LinearLayout.VERTICAL)
 detailsLayout.setPadding(20,20,20,20)
 scrollLayout.addView(detailsLayout)
 local function addDetail(label,value)
  local detailLayout=LinearLayout(service)
  detailLayout.setOrientation(LinearLayout.VERTICAL)
  detailLayout.setPadding(0,10,0,10)
  local labelView=TextView(service)
  labelView.setText(label)
  labelView.setTextSize(14)
  labelView.setTextColor(0xFF808080)
  detailLayout.addView(labelView)
  local valueView=TextView(service)
  valueView.setText(value)
  valueView.setTextSize(16)
  valueView.setTextColor(0xFF000000)
  detailLayout.addView(valueView)
  detailsLayout.addView(detailLayout)
 end
 local function getFormattedDate(timestamp)
  if not timestamp then return "غير متوفر" end
  local date=luajava.newInstance("java.util.Date",timestamp)
  local format=luajava.newInstance("java.text.SimpleDateFormat","MMMM dd, yyyy 'في' hh:mm:ss a")
  return tostring(format.format(date))
 end
 local appInfo=packageInfo.applicationInfo
 local apkFile=luajava.newInstance("java.io.File",tostring(appInfo.sourceDir))
 local appSizeMB="غير متوفر"
 if apkFile and apkFile.exists() then
  local size=apkFile.length()
  appSizeMB=string.format("%.2f ميغابايت",size/(1024*1024))
 end
 addDetail("اسم التطبيق",tostring(appInfo.loadLabel(packageManager)))
 addDetail("اسم الحزمة",packageName)
 addDetail("اسم الإصدار",tostring(packageInfo.versionName))
 addDetail("كود الإصدار",tostring(packageInfo.versionCode))
 addDetail("تم التثبيت في",getFormattedDate(packageInfo.firstInstallTime))
 addDetail("آخر تحديث",getFormattedDate(packageInfo.lastUpdateTime))
 addDetail("الحجم",appSizeMB)
 local installerPackageName=packageManager.getInstallerPackageName(packageName)
 local installerInfo="مصدر غير معروف"
 if installerPackageName then
  if installerPackageName=="com.android.vending" then installerInfo="متجر Google Play" else installerInfo=installerPackageName end
 end
 addDetail("تم التثبيت بواسطة",installerInfo)
 local moreInfoButton=Button(service)
 moreInfoButton.setText("مزيد من المعلومات")
 local moreInfoParams=LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT)
 moreInfoParams.topMargin=20
 moreInfoButton.setLayoutParams(moreInfoParams)
 moreInfoButton.onClick=function()
  local intent=Intent()
  intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
  intent.setData(Uri.parse("package:"..packageName))
  service.startActivity(intent)
  appDetailsDialog.dismiss()
  dlg.dismiss()
 end
 detailsLayout.addView(moreInfoButton)
 appDetailsDialog.setView(scrollLayout)
 appDetailsDialog.setTitle("تفاصيل التطبيق")
 appDetailsDialog.setNegativeButton("إغلاق",nil)
 appDetailsDialog.show()
end

listView.onItemLongClick=function(parent,view,position,id)
 local selectedName=parent.getAdapter().getItem(position)
 local data=appData.get(selectedName)
 if currentAudioPlayer and currentAudioPlayer.isPlaying() then currentAudioPlayer.stop() currentAudioPlayer.release() currentAudioPlayer=nil end
 local options={}
 local favOption=""
 if data and data.isComponent then
  local packageName=data.packageName
  local componentName=data.componentName
  local isFav=false
  local favEntry=packageName.."|"..componentName
  for _,fav in ipairs(favoriteComponents) do if fav==favEntry then isFav=true break end end
  favOption=isFav and "إزالة من المفضلة" or "إضافة إلى المفضلة"
  table.insert(options,favOption)
  table.insert(options,"نسخ الكود")
  table.sort(options)
  local menu=LuaDialog(service)
  menu.setTitle("خيارات لـ "..selectedName)
  menu.setItems(options)
  menu.onItemClick=function(_,_,selected)
   local selectedOption=options[selected+1]
   if selectedOption==favOption then
    local currentQuery=tostring(searchEditText.getText())
    if isFav then
     for i,fav in ipairs(favoriteComponents) do if fav==favEntry then table.remove(favoriteComponents,i) break end end
     Toast.makeText(service,"تم إزالة المكوّن من المفضلة",Toast.LENGTH_SHORT).show()
    else
     table.insert(favoriteComponents,favEntry)
     Toast.makeText(service,"تم إضافة المكوّن إلى المفضلة",Toast.LENGTH_SHORT).show()
    end
    saveFavoriteComponents(favoriteComponents)
    loadApplications(types[appTypeSpinner.getSelectedItemPosition()+1],currentQuery)
   elseif selectedOption=="نسخ الكود" then
    local code='i=luajava.bindClass("android.content.Intent")()\ni.setClassName("'..packageName..'", "'..componentName..'")\nservice.startActivity(i)'
    service.copy(code)
    Toast.makeText(service,"تم نسخ الكود إلى الحافظة!",Toast.LENGTH_SHORT).show()
   end
   menu.dismiss()
  end
  menu.setNegativeButton("إغلاق",nil)
  menu.show()
  return true
 end
 local packageName=data.packageName
 local isFavorite=false
 for _,favPkg in ipairs(favoritePackages) do if favPkg==packageName then isFavorite=true break end end
 favOption=isFavorite and "إزالة من المفضلة" or "إضافة إلى المفضلة"
 options={"إضافة إلى المفضلة","إزالة من المفضلة","استخراج الصوت","استخراج الصور","استخراج ملف APK","مشاركة التطبيق","معلومات التطبيق","إلغاء تثبيت التطبيق","فتح في متجر Play","مشاركة رابط التطبيق","الحصول على اسم الحزمة","عرض الأنشطة"}
 for i=#options,1,-1 do if options[i]==favOption then table.remove(options,i) break end end
 table.insert(options,1,favOption)
 table.sort(options)
 local menu=LuaDialog(service)
 menu.setTitle("خيارات لـ "..selectedName)
 menu.setItems(options)
 menu.onItemClick=function(_,_,selected)
  local selectedOption=options[selected+1]
  local currentQuery=tostring(searchEditText.getText())
  if selectedOption==favOption then
   if isFavorite then
    for i,favPkg in ipairs(favoritePackages) do if favPkg==packageName then table.remove(favoritePackages,i) break end end
    Toast.makeText(service,"تمت الإزالة من المفضلة",Toast.LENGTH_SHORT).show()
   else
    table.insert(favoritePackages,packageName)
    Toast.makeText(service,"تمت الإضافة إلى المفضلة",Toast.LENGTH_SHORT).show()
   end
   saveFavorites(favoritePackages,"AppFavorites")
   loadApplications(types[appTypeSpinner.getSelectedItemPosition()+1],currentQuery)
  elseif selectedOption=="معلومات التطبيق" then showAppDetails(packageName)
  elseif selectedOption=="الحصول على اسم الحزمة" then service.copy(packageName) Toast.makeText(service,"تم نسخ اسم الحزمة: "..packageName,Toast.LENGTH_LONG).show()
  elseif selectedOption=="عرض الأنشطة" then displayComponents(packageName)
  elseif selectedOption=="استخراج الصوت" then extractAudioFiles(packageName)
  elseif selectedOption=="استخراج الصور" then extractImageFiles(packageName)
  elseif selectedOption=="استخراج ملف APK" or selectedOption=="مشاركة التطبيق" then
   local packageInfo=packageManager.getPackageInfo(packageName,0)
   if packageInfo.applicationInfo.sourceDir then
    local apkPath=packageInfo.applicationInfo.sourceDir
    local appLabel=tostring(packageManager.getApplicationLabel(packageInfo.applicationInfo))
    local versionName=tostring(packageInfo.versionName or "1.0")
    local fileName=string.format("%s_v%s.apk",appLabel,versionName)
    local externalDir=File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),"مدير تطبيقات أندرويد SAYAHFETHI")
    externalDir.mkdirs()
    local destFile=File(externalDir,fileName)
    LuaUtil.copyFile(apkPath,destFile.getAbsolutePath())
    
    if selectedOption=="مشاركة التطبيق" then
     menu.dismiss()
     dlg.dismiss()
     
     local homeIntent=Intent(Intent.ACTION_MAIN)
     homeIntent.addCategory(Intent.CATEGORY_HOME)
     homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
     service.startActivity(homeIntent)
     
     local sendIntent=Intent(Intent.ACTION_SEND)
     sendIntent.setType("application/vnd.android.package-archive")
     sendIntent.putExtra(Intent.EXTRA_STREAM,service.getUriForFile(destFile))
     sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
     sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
     service.startActivity(Intent.createChooser(sendIntent,"مشاركة التطبيق"))
    else
     Toast.makeText(service,"تم استخراج APK باسم:\n"..fileName,Toast.LENGTH_LONG).show()
    end
   else
    Toast.makeText(service,"تعذر الحصول على مسار ملف APK",Toast.LENGTH_SHORT).show()
   end
  elseif selectedOption=="فتح في متجر Play" then
   local intent=Intent(Intent.ACTION_VIEW)
   intent.setData(Uri.parse("market://details?id="..packageName))
   service.startActivity(intent)
   dlg.dismiss()
  elseif selectedOption=="مشاركة رابط التطبيق" then
   local playStoreLink="https://play.google.com/store/apps/details?id="..packageName
   local shareIntent=Intent(Intent.ACTION_SEND)
   shareIntent.setType("text/plain")
   shareIntent.putExtra(Intent.EXTRA_TEXT,playStoreLink)
   service.startActivity(Intent.createChooser(shareIntent,"مشاركة رابط التطبيق"))
   dlg.dismiss()
  elseif selectedOption=="إلغاء تثبيت التطبيق" then
   local intent=Intent(Intent.ACTION_DELETE)
   intent.setData(Uri.parse("package:"..packageName))
   service.startActivity(intent)
   dlg.dismiss()
  end
  menu.dismiss()
 end
 menu.setNegativeButton("عودة",nil)
 menu.show()
 return true
end

return true
